package updown.data;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import updown.constant.GeneralConstant;
import updown.domain.TaskInfo;
import updown.domain.TaskWrapper;
import updown.service.task.TaskInfoService;
import updown.service.updown.DownUpServiceWithRetry;
import updown.util.Constant;
import updown.util.SleepUtil;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>Title: ww.kaixin.downupservice.data </p>
 * <p>Description:updown: -  </p>
 *
 * @Author:jiangkaixin
 * @Date:2021/11/3
 * @Version: 1.0
 */
@Slf4j
@Service
public class SseCacheData {
    @Autowired
    private TaskInfoService taskInfoService;

    private static Map<String, SseEmitter> sseCache = new ConcurrentHashMap<>();

    /**
     * 保存事件
     *
     * @param taskId
     * @param sseEmitter
     */
    public void put(String taskId, SseEmitter sseEmitter) {
        sseCache.put(taskId, sseEmitter);
    }

    /**
     * 移除事件任务，表示结束
     *
     * @param task
     */
    public void remove(String taskId) {
        sseCache.remove(taskId);
    }

    /**
     * 根据 taskId  返回 SseEmitter
     *
     * @param taskId
     * @return
     */
    public SseEmitter getByTaskId(String taskId) {
        SseEmitter emitter = sseCache.get(taskId);
        if (emitter == null) {
            throw new RuntimeException("没有对应的emmit");
        }
        return emitter;
    }

    /**
     * 发送最后的消息，然后关闭通道
     *
     * @param msg
     * @param taskId
     */
    public void sendLastMsgAndComplete(String msg, TaskWrapper taskWrapper) {
        if (GeneralConstant.TASK_WRAPPER_DOWN_UP_SCHEDULE.equals(taskWrapper.getTaskType())){
            return;
        }
        SseEmitter emitter = getByTaskId(taskWrapper.getTaskId());
        try {
            emitter.send(msg);
        } catch (IOException e) {
            log.info("log.info:sendLastMsgAndComplete >>>:{}", e);
        } finally {
            emitter.complete();
            sseCache.remove(taskWrapper.getTaskId());
            taskWrapper.endSuccess(Boolean.TRUE);
            // 保存到 task 数据库
            try {
                taskInfoService.add(taskWrapper);
            } catch (Exception e) {
                log.info("sendLastMsgAndComplete - addTaskWrapper:{}",e);
            }
        }
    }

    /**
     * 发送最后的消息，然后报错， 关闭通道
     *
     * @param msg
     * @param taskId
     */
    public void sendLastMsgAndThrowEx(String msg, TaskWrapper taskWrapper) {
        if (GeneralConstant.TASK_WRAPPER_DOWN_UP_SCHEDULE.equals(taskWrapper.getTaskType())){
            return;
        }
        SseEmitter emitter = getByTaskId(taskWrapper.getTaskId());
        try {
            emitter.send(msg);
        } catch (IOException e) {
            log.info("log.info:sendLastMsgAndComplete >>>:{}", e);
        } finally {
            // emmiter 处理
            emitter.complete();
            sseCache.remove(taskWrapper.getTaskId());
            // 保存最后的 msg 信息作为最后一个任务
            TaskInfo exTask = TaskInfo.builder().taskDes(msg).success(Boolean.FALSE).build();
            exTask.finished();
            taskWrapper.getTaskInfos().add(exTask);
            taskWrapper.endFail();
            try {
                if (!GeneralConstant.TASK_WRAPPER_TYPE.equals(taskWrapper.getTaskType())){
                    // 取消正在替换中的状态
                    DownUpServiceWithRetry.downDownMap.remove(taskWrapper.getServiceInfo().getServiceName());
                    log.info("{}:取消正在替换中的状态",taskWrapper.getServiceInfo().getServiceName());
                }
                taskInfoService.add(taskWrapper);
            } catch (Exception e) {
                log.info("保存 task 信息到数据库 失败:{}",e);
            }
            throw new RuntimeException(msg);
        }
    }

    public void sendLastMsgAndCompleteInPool(String msg, TaskWrapper taskWrapper) {
        ExecutorPoolUtil.executor.execute(()->{
            SleepUtil.sleepSeconds(1);
            sendLastMsgAndThrowEx(msg, taskWrapper);
        });
    }

    /**
     * 发送数据
     *
     * @param s      发送的消息
     * @param taskId 任务id
     */
    public void pushMsg(String msg, TaskWrapper taskWrapper) {
        if (GeneralConstant.TASK_WRAPPER_DOWN_UP_SCHEDULE.equals(taskWrapper.getTaskType())){
            return;
        }
        SseEmitter emitter = getByTaskId(taskWrapper.getTaskId());
        try {
            emitter.send(msg);
        } catch (IOException e) {
            log.info("log.info:sendLastMsgAndComplete >>>:{}", e);
        }
    }
}
